import re
import json
import numpy as np
# from bladder_foil_four_for_vscode import FOIL


def get_total_list1(input_list):
    total_list = []
    total_object = ["DIS1", "DIS2", "DIS3", "DIS4", "DIS5", "DIS6", "DIS7", "DIS8", 'DIV']
    # total_object = ["DIS1", "DIS2", "DIS3", "DIS4", "DIS5", "DIS6", "DIS7", "DIS8"]
    # total_object = ["DIS1", "DIS2", "DIS3", "DIS4", "DIS5", "DIS6", "DIS7", "DIS8", "DIS9", "DIS10", "DIS11", "DIS12"]
    for image_num in range(len(input_list)):
        try:
            image_list = []
            # print(str(input_list[image_num]['imageId']))
            # string=input_list[image_num]['type'] + "(" + str(input_list[image_num]['imageId'])+")"
            # image_list.append(string)
            # print(input_list[image_num])
            x1, y1, x2, y2 = map(float, input_list[image_num]['object_detect']['object']['0']['coordinate'])
            x3, y3, x4, y4 = map(float, input_list[image_num]['object_detect']['object']['1']['coordinate'])
            x5, y5 = map(float, input_list[image_num]['object_detect']['point']['0']['position'])
            x6, y6 = map(float, input_list[image_num]['object_detect']['point']['1']['position'])
            for index, object in enumerate(total_object):
                has = object + "(" + input_list[image_num]["imageId"] + "," + str(index) + ")"
                if object == 'DIS1':
                    p = "dis(" + str(index) + "," + str(x1 - x3) + ")"
                elif object == 'DIS2':
                    p = "dis(" + str(index) + "," + str(y1 - y3) + ")"
                elif object == 'DIS3':
                    p = "dis(" + str(index) + "," + str(x2 - x4) + ")"
                elif object == 'DIS4':
                    p = "dis(" + str(index) + "," + str(y2 - y4) + ")"
                elif object == 'DIS5':
                    p = "dis(" + str(index) + "," + str(x6 - x5) + ")"
                elif object == 'DIS6':
                    p = "dis(" + str(index) + "," + str(y6 - y5) + ")"
                elif object == 'DIS7':
                    p = "dis(" + str(index) + "," + str(y5 - y3) + ")"
                elif object == 'DIS8':
                    p = "dis(" + str(index) + "," + str(y6 - y1) + ")"
                elif object == 'DIS9':
                    p = "dis(" + str(index) + "," + str(x2 - x1) + ")"
                elif object == 'DIS10':
                    p = "dis(" + str(index) + "," + str(y2 - y1) + ")"
                elif object == 'DIS11':
                    p = "dis(" + str(index) + "," + str(x4 - x3) + ")"
                elif object == 'DIS12':
                    p = "dis(" + str(index) + "," + str(y4 - y3) + ")"
                else:
                    area1 = (x2 - x1) * (y2 - y1)
                    area2 = (x4 - x3) * (y4 - y3)
                    p = "area(" + str(index) + "," + str(area2 / area1) + ")"
                image_list.append(has)
                image_list.append(p)
            total_list.append(image_list)
        except:
            print(input_list[image_num])
    return total_list


def get_total_listt(total_list1):
    total_list = []
    for image in total_list1:
        list = []
        for clauses in image:
            a = re.split(r'[(|,|)]', clauses)
            if a[0] != 'overlap' and a[0] != 'dis' and a[0] != 'area':
                sub = a[1]
                break
        for clauses in image:
            a = re.split(r'[¬|(|,|)]', clauses)
            if a[1] == sub:
                a[1] = "X"
                if len(a) == 3:
                    result = a[0] + "(" + a[1] + ")" + a[2]
                else:
                    result = a[0] + "(" + a[1] + "," + a[2] + ")" + a[3]
                list.append(result)
            elif a[2] == sub:
                a[2] = "X"
                result = "¬" + a[1] + "(" + a[2] + "," + a[3] + ")" + a[4]
                list.append(result)
            else:
                result = a[0] + "(" + a[1] + "," + a[2] + ")" + a[3]
                list.append(result)
        total_list.append(list)
    return total_list


def labeling(total_list, rules):
    labels = []
    possible_labels = []
    for possible_label in rules.keys():
        possible_labels.append(possible_label)
    for image in total_list:
        image_ratio = []
        for possible_label in possible_labels:
            rule_list = rules[possible_label]
            ratio_list = []
            for rule_num, rule in enumerate(rule_list):
                object_in_rule = []
                object_character = []
                rule_length = len(rule)
                satisfy_number = 0
                for position, clauses in enumerate(rule):
                    a = re.split(r'[¬|(|,|)]', clauses)
                    if len(a) == 5:
                        for predicate in image:
                            b = re.split(r'[¬|(|,|)]', predicate)
                            if b[1] == a[1]:
                                satisfy_number += 1
                                break
                    elif a[0] != 'overlap' and a[0] != 'dis' and a[0] != 'area' and len(a) == 4:
                        object_in_rule.append(a[0])
                        object_character.append(a[2])
                        for predicate in image:
                            b = re.split(r'[(|,|)]', predicate)
                            if b[0] == a[0]:
                                satisfy_number += 1
                                break
                    elif a[0] == 'dis' or a[0] == 'area':
                        object_in_image = []
                        object_number = []
                        object1_in_rule = object_in_rule[object_character.index(a[1])]
                        for predicate in image:
                            b = re.split(r'[(|,|)]', predicate)
                            if b[0] != 'overlap' and b[0] != 'dis' and b[0] != 'area':
                                object_in_image.append(b[0])
                                object_number.append(b[2])
                            if b[0] == a[0]:
                                object1_in_image = object_in_image[object_number.index(b[1])]
                                c = re.split(r'[<]', rule[position + 1])
                                if len(c) != 1:
                                    maxi = float(c[1])
                                    if object1_in_image == object1_in_rule and float(b[2]) <= maxi:
                                        satisfy_number += 2
                                        break
                                else:
                                    c = re.split(r'[>]', rule[position + 1])
                                    mini = float(c[1])
                                    if object1_in_image == object1_in_rule and mini < float(b[2]):
                                        satisfy_number += 2
                                        break
                ratio = satisfy_number / rule_length
                ratio_list.append(ratio)
            # print(ratio_list)
            cnt = 0
            for ratio in ratio_list:
                if ratio == 1:
                    cnt += 1
            image_ratio.append(cnt / len(ratio_list))
        index = np.argmax(np.array(image_ratio))
        # print(image_ratio)
        labels.append([possible_labels[index]])
    return labels


def AL(total_list, rules):
    possible_labels = []
    result = []
    for possible_label in rules.keys():
        possible_labels.append(possible_label)
    for image in total_list:
        image_ratio = []
        for possible_label in possible_labels:
            rule_list = rules[possible_label]
            ratio_list = []
            for rule_num, rule in enumerate(rule_list):
                object_in_rule = []
                object_character = []
                rule_length = len(rule)
                satisfy_number = 0
                for position, clauses in enumerate(rule):
                    a = re.split(r'[¬|(|,|)]', clauses)
                    if len(a) == 5:
                        for predicate in image:
                            b = re.split(r'[¬|(|,|)]', predicate)
                            if b[1] == a[1]:
                                satisfy_number += 1
                                break
                    elif a[0] != 'overlap' and a[0] != 'dis' and a[0] != 'area' and len(a) == 4:
                        object_in_rule.append(a[0])
                        object_character.append(a[2])
                        for predicate in image:
                            b = re.split(r'[(|,|)]', predicate)
                            if b[0] == a[0]:
                                satisfy_number += 1
                                break
                    elif a[0] == 'dis' or a[0] == 'area':
                        object_in_image = []
                        object_number = []
                        object1_in_rule = object_in_rule[object_character.index(a[1])]
                        for predicate in image:
                            b = re.split(r'[(|,|)]', predicate)
                            if b[0] != 'overlap' and b[0] != 'dis' and b[0] != 'area':
                                object_in_image.append(b[0])
                                object_number.append(b[2])
                            if b[0] == a[0]:
                                object1_in_image = object_in_image[object_number.index(b[1])]
                                c = re.split(r'[<]', rule[position + 1])
                                if len(c) != 1:
                                    maxi = float(c[1])
                                    if object1_in_image == object1_in_rule and float(b[2]) <= maxi:
                                        satisfy_number += 2
                                        break
                                else:
                                    c = re.split(r'[>]', rule[position + 1])
                                    mini = float(c[1])
                                    if object1_in_image == object1_in_rule and mini < float(b[2]):
                                        satisfy_number += 2
                                        break
                ratio = satisfy_number / rule_length
                ratio_list.append(ratio)
            # print(ratio_list)
            cnt = 0
            for ratio in ratio_list:
                if ratio == 1:
                    cnt += 1
            image_ratio.append(cnt / len(ratio_list))
        # print(image_ratio)
        result.append(image_ratio)
    return result


def label(dict_list, rules):
    total_list1 = get_total_list1(dict_list)
    total_list = get_total_listt(total_list1)
    al = AL(total_list, rules)
    labels = labeling(total_list, rules)
    return labels, al


# if __name__ == '__main__':
#     with open('../../data/dataset/bladder4/test.json', 'r', encoding='utf-8') as fp:
#         data = json.load(fp)
#     rules = FOIL(data, {}, {})[0]
#     # print(rules)
#     print(label(data, rules))
    # print(FOIL(data, {}, {})[1])
